﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Budget.DataAccess.Repository;
using Budget.HelperClasses;

namespace Budget.DataAccess.Services
{
	public class SpendingDataService : ISpendingDataService
	{
		private IRepository<Spending> sRepo;
		private IRepository<MthCategory> mcRepo;

		public SpendingDataService( IRepository<Spending> repository )
		{
			sRepo = repository;
		}
		public SpendingDataService( IRepository<Spending> repository, IRepository<MthCategory> mthCategoryRepository )
		{
			sRepo = repository;
			mcRepo = mthCategoryRepository;
		}

		#region ISpendingDataService Members

		public bool SpendingsExistForMonthYear( int month, int year )
		{
			bool exists = false;

			using ( sRepo )
			{
				exists = sRepo.Query().Where( s => s.DateSpent.Month == month && s.DateSpent.Year == year ).Count() > 0;
			}

			return exists;
		}

		public bool SpendingsExistForMonth( int mthId )
		{
			bool exists = false;

			using ( sRepo )
			{
				exists = sRepo.Query().Where( s => s.MthCategory.MthId == mthId ).Count() > 0;
			}

			return exists;
		}

		public IList<MonthSummary> GetMonthCategorySummary( DateTime analysisDate )
		{
			IList<MonthSummary> mcSummaryList = new List<MonthSummary>();
			IList<Spending> relevantSpendings;
			IList<MthCategory> relevantCategories;

			using ( sRepo )
			{
				relevantSpendings = ( from s in sRepo.Query()
									  where s.DateSpent.Month == analysisDate.Month && s.DateSpent.Year == analysisDate.Year
									  select s ).ToList();

				using ( mcRepo )
				{
					relevantCategories = ( from mc in mcRepo.Query()
										   where mc.Mth.Month == analysisDate.Month && mc.Mth.Year == analysisDate.Year
										   select mc ).ToList();

					var initial = from mc in relevantCategories
								  join s in relevantSpendings on mc.MthCategoryId equals s.MthCategoryId into g
								  from s in g.DefaultIfEmpty()
								  select new MonthSummary
								  {
									  MthCategoryId = mc.MthCategoryId,
									  CategoryId = mc.CategoryId,
									  CategoryName = mc.Category.CategoryName,
									  BudgetAmount = mc.BudgetAmount,
									  AmountSpent = s == null ? 0m : s.Amount
								  };

					mcSummaryList = ( from i in initial
									  group i by i.CategoryId into g
									  orderby g.Key ascending
									  select new MonthSummary
									  {
										  MthCategoryId = g.FirstOrDefault() == null ? 0 : ( (MonthSummary) g.FirstOrDefault() ).MthCategoryId,
										  CategoryId = g.Key,
										  CategoryName = g.FirstOrDefault() == null ? string.Empty : ( (MonthSummary) g.FirstOrDefault() ).CategoryName,
										  AmountSpent = g.Sum( ms => ms.AmountSpent ),
										  BudgetAmount = g.FirstOrDefault() == null ? 0m : ( (MonthSummary) g.FirstOrDefault() ).BudgetAmount
									  } ).ToList();
				}
			}

			return mcSummaryList;
		}

		public IList<Spending> GetSpendingsByMonthAndYear( int month, int year )
		{
			IList<Spending> spendings;

			using ( sRepo )
			{
				spendings = sRepo.Query().Where( s => s.DateSpent.Month == month && s.DateSpent.Year == year ).ToList();
			}

			return spendings;
		}

		public IList<Spending> GetSpendingsByMonth( int mthId )
		{
			IList<Spending> spendings;

			using ( sRepo )
			{
				spendings = sRepo.Query().Where( s => s.MthCategory.MthId == mthId ).ToList();
			}

			return spendings;
		}

		public void Save( Spending spending )
		{
			using ( sRepo )
			{
				if ( spending.SpendingId == 0 )
				{
					sRepo.Add( spending );
				}
				else
				{
					sRepo.Attach( spending );
				}

				sRepo.SubmitChanges();
			}
		}

		public IList<Spending> GetSpendingsByMthCategoryId( int MthCategoryId )
		{
			IList<Spending> spendings;

			using ( sRepo )
			{
				spendings = sRepo.Query().Where( s => s.MthCategoryId == MthCategoryId ).ToList();
			}

			return spendings;
		}

		#endregion
	}
}
